package com.grad.webstudy.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.grad.webstudy.enums.StatusEnums;
import com.grad.webstudy.model.es.ESCourse;
import com.grad.webstudy.model.es.ESLog;
import com.grad.webstudy.service.ElasticSearchService;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description:
 * @Author: zjf
 * @Date: 2020/4/1 11:52.
 */
@Service
public class ElasticSearchServiceImpl implements ElasticSearchService {


    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public void saveToES(ESLog EsLog) {

        IndexQuery indexQuery = new IndexQueryBuilder()
                .withObject(EsLog)
                .build();

        elasticsearchTemplate.index(indexQuery);
    }

    @Override
    public Page<ESCourse> queryByKeyWord(String keyword, Integer currPage) {

        Page<ESCourse> result = null;

        String preTag = "<font color='#dd4b39'>";//google的色值
        String postTag = "</font>";

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        boolQueryBuilder.must(QueryBuilders.termQuery("status", StatusEnums.ONLINE.getStatus()));

        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder.must(QueryBuilders.multiMatchQuery(keyword, "class_name", "introduction")))
                .withPageable(PageRequest.of(currPage - 1, 10))
                .withHighlightFields(new HighlightBuilder.Field("class_name").preTags(preTag).postTags(postTag),
                        new HighlightBuilder.Field("introduction").preTags(preTag).postTags(postTag))
                .build();

        result = elasticsearchTemplate.queryForPage(searchQuery, ESCourse.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<ESCourse> chunk = new ArrayList<>();
                for (SearchHit searchHit : searchResponse.getHits()) {
                    if (searchResponse.getHits().getHits().length <= 0) {
                        return null;
                    }

                    ESCourse esCourse = new ESCourse();

                    esCourse.setId(Integer.valueOf(searchHit.getId()));
                    esCourse.setCoverPath((String) searchHit.getSourceAsMap().get("cover_path"));
                    esCourse.setLevel((Integer) searchHit.getSourceAsMap().get("level"));
                    String teacher =  searchHit.getSourceAsMap().get("teacher").equals("admin")?"官方": (String) searchHit.getSourceAsMap().get("teacher");
                    esCourse.setTeacher(teacher);
                    HighlightField ideaTitle = searchHit.getHighlightFields().get("class_name");
                    if (ideaTitle != null) {
                        esCourse.setClassName(ideaTitle.fragments()[0].toString());
                    }else{
                        esCourse.setClassName((String) searchHit.getSourceAsMap().get("class_name"));
                    }
                    HighlightField ideaContent = searchHit.getHighlightFields().get("introduction");
                    if (ideaContent != null) {
                        esCourse.setIntroduction(ideaContent.fragments()[0].toString());
                    }else{
                        esCourse.setIntroduction((String) searchHit.getSourceAsMap().get("introduction"));
                    }

                    chunk.add(esCourse);


                }
                if (chunk.size() > 0) {
                    return new AggregatedPageImpl<>((List<T>) chunk);
                }
                return null;
            }


            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                return null;
            }
        });


        return result;
    }

    @Override
    public AggregatedPage<ESLog> queryAllLog(Integer currPage, Integer pageSize) {


        Sort sort = Sort.by(Sort.Direction.DESC, "time");

        Pageable page = PageRequest.of(currPage - 1, pageSize, sort);


        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withPageable(page)
                .build();

        return elasticsearchTemplate.queryForPage(searchQuery, ESLog.class);

    }

    @Override
    public void deleteESCourse(String id) {

        elasticsearchTemplate.delete(ESCourse.class, id);
    }


}
